package utils;

import java.util.Arrays;

import odesimulation.crnLexer;
import odesimulation.crnParser;
import odesimulation.crnParser.ReactionsetContext;

import org.antlr.v4.runtime.ANTLRInputStream;
import org.antlr.v4.runtime.CommonTokenStream;

import picoevo.app.chemicalreactions.Global_CR;
import picoevo.app.chemicalreactions.Individual_CR;
import picoevo.core.Population;

public class IndividualGenerator {

	public static Individual_CR generateFromDescription(String descr, Population owner){
		Individual_CR indiv = new Individual_CR(owner, false); // we do the initialization by ourself
		
		//Lexing the equations
		crnLexer myLex = new crnLexer(new ANTLRInputStream(descr));
		//Parsing the equations
		crnParser myPars = new crnParser(new CommonTokenStream(myLex));
		//Parsing result
		//Contains "symbols": X,Y,Z... list of all substrats.
		//		   "enzymes": E1... list of all enzymes.
		//         "reactions": list of all reactions.
		ReactionsetContext context = myPars.reactionset();
		
		//initial concentrations for substrats: 10 nM all around!
		double[] init = new double[context.symbols.size()];
		
		double[][] matrix_Km = new double[context.enzymenames.size()][context.symbolList.size()];
		double[][] matrix_ki = new double[context.enzymenames.size()][context.symbolList.size()];
		
		//put in the enzyme matrix
		for(int i = 0; i < context.enzymenames.size(); i++){
			for(int j = 0; j < context.symbolList.size(); j++){
				
				matrix_Km[i][j] = context.Kmvalues.get(i).get(j);
				matrix_ki[i][j] = context.kivalues.get(i).get(j);
				
			}
		}
		
		indiv.setMatrixKm(matrix_Km);
		indiv.setMatrixKi(matrix_ki);
		
		for(int i = 0; i < context.reactions.size(); i++){
			picoevo.app.chemicalreactions.Reaction reac = new picoevo.app.chemicalreactions.Reaction(false);
			int[] signature = new int[6];
			Arrays.fill(signature, -1);
			
			odesimulation.Reaction current = context.reactions.get(i);
			
			if(current.getClass()==odesimulation.EnzymaticReaction.class){
				String enzyme = ((odesimulation.EnzymaticReaction) current).getEnzyme();
				signature[0] = context.enzymenames.indexOf(enzyme);
				signature[3] = signature[0];
			} 
			
			signature[1] = current.reactants.size() >= 1? context.symbolList.indexOf(current.reactants.get(0)):-1;
			signature[2] = current.reactants.size() >= 2? context.symbolList.indexOf(current.reactants.get(1)):-1;
			
			signature[4] = current.products.size() >= 1? context.symbolList.indexOf(current.products.get(0)):-1;
			signature[5] = current.products.size() >= 2? context.symbolList.indexOf(current.products.get(1)):-1;
		
			if(current.getClass()==odesimulation.EnzymaticReaction.class){
				reac.setSignature(signature);
			} else {
				reac.setSignature(signature,current.reactionRate,current.reverseReactionRate);
			}
			indiv.addReaction(reac);
		}
		
		
		return indiv;
	}
	
	public static void main(String[] args){
	String testIndiv = "enzymes: E1 E2 E3"+
	"products: X Y Z"+
	"K_m[3][3] : { { 1.6473004524935453 0.6940152809604029 0.10603294458960277 }{ 3.8480624501152283 7.270336094048727 0.23178914435416556 }{ 3.6380853207832695 0.21837670215845575 5.171245798749581 } }"+
	"k_i[3][3] : { { 1.0 7.138817273404403 7.817161630697303 }{ 0.18629808135361342 6.287341109478218 3.1881687125316103 }{ 0.28570237195557774 2.589996881474015 1.1837361383402576 } }"+
	"E1 + Z ==> E1"+
	"Y + Z <==> Z + X [ k+ = 0.5760142791697347 ; k- = 0.20035166414249178 ]"+
	"E3 + Y ==> E3 + Y"+
	"X + Z <== Y + Y [ k+ = 0.0 ; k- = 4.158412550244926 ]";
	
	Individual_CR gr = generateFromDescription(testIndiv, null);
	
	gr.displayInformation();
		
	}
	
}
